package com.seleniti.enpareja.web.desktop.client.ui.view;

import org.ioc.commons.impl.gwt.client.model.dataprovider.AsyncPagedDataProvider;
import org.ioc.commons.impl.gwt.client.ui.HasEnabledWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasValueWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasVisibilityWrapper;
import org.ioc.commons.model.dataprovider.PagedDataProvider;
import org.ioc.commons.ui.HasValue;
import org.ioc.commons.ui.HasVisibility;
import org.ioc.commons.ui.features.Info;

import com.google.gwt.cell.client.AbstractSafeHtmlCell;
import com.google.gwt.cell.client.SafeHtmlCell;
import com.google.gwt.cell.client.SimpleSafeHtmlCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.text.shared.AbstractSafeHtmlRenderer;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.SearchTextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.seleniti.enpareja.controller.model.integration.database.domain.CoupleType;
import com.seleniti.enpareja.controller.model.integration.database.domain.Gender;
import com.seleniti.enpareja.controller.model.integration.database.domain.User;
import com.seleniti.enpareja.controller.ui.view.CoupleRequestsView;
import com.seleniti.enpareja.controller.ui.view.CoupleRequestsView.Action;
import com.seleniti.enpareja.controller.ui.view.CoupleRequestsView.Event;
import com.seleniti.enpareja.controller.ui.view.CoupleRequestsView.Operation;
import com.seleniti.enpareja.controller.ui.view.CoupleRequestsView.Presenter;
import com.seleniti.enpareja.controller.ui.view.CoupleRequestsViewPresenter;
import com.seleniti.enpareja.web.desktop.client.ui.cell.EnParejaTemplate;
import com.seleniti.enpareja.web.desktop.client.ui.resources.CommonResources;
import com.seleniti.enpareja.web.desktop.client.ui.widget.InfoInlineWidget;

public class CoupleRequestsViewWidget extends EnParejaBaseView<Event, Operation, Action, Presenter> implements
		CoupleRequestsView {

	public static EnParejaTemplate template;

	private static TemplateUiBinder uiBinder = GWT.create(TemplateUiBinder.class);

	interface TemplateUiBinder extends UiBinder<Widget, CoupleRequestsViewWidget> {
	}

	public static interface Style extends CssResource {

		String pendingRequests();

	}

	@UiField
	SearchTextBox searchBox;

	@UiField(provided = true)
	DataGrid<User> lstUsers;

	@UiField(provided = true)
	SimplePager pager;

	@UiField
	InfoInlineWidget ableToGetCoupleInfo;

	@UiField
	InfoInlineWidget unableToGetCoupleInfo;

	@UiField
	InfoInlineWidget requestSentInfo;

	@UiField
	InfoInlineWidget requestAlreadyMadeInfo;

	@UiField
	InfoInlineWidget coupleGotInfo;

	@UiField
	Button btnMakeCoupleRequest;

	@UiField
	CommonResources common;

	@UiField
	Style style;

	private PagedDataProvider<User> pagedDataProvider;

	private AsyncPagedDataProvider<User, Operation> asyncDataProvider;

	private SingleSelectionModel<User> selectionModel;

	private boolean loading;

	public CoupleRequestsViewWidget() {
		if (template == null) {
			template = GWT.create(EnParejaTemplate.class);
		}

		this.presenter = new CoupleRequestsViewPresenter(this, eventbus, operationManager, actionController);

		ProvidesKey<User> keyProvider = new ProvidesKey<User>() {

			@Override
			public Object getKey(User item) {
				return item.getUserId();
			}
		};
		this.lstUsers = new DataGrid<User>(keyProvider);

		this.lstUsers.addColumn(new Column<User, SafeHtml>(new SimpleSafeHtmlCell()) {

			@Override
			public SafeHtml getValue(User object) {
				return object != null && object.getUserEmail() != null && !object.getUserEmail().isEmpty() ? maskEmail(object
						.getUserEmail()) : SafeHtmlUtils.fromSafeConstant("-- Sin email --");
			}
		}, "Email");

		this.lstUsers.addColumn(new Column<User, String>(new TextCell()) {

			@Override
			public String getValue(User object) {
				return object != null && object.getNickName() != null && !object.getNickName().isEmpty() ? object
						.getNickName() : "-- Sin nombre --";
			}
		}, "Nombre");

		AbstractSafeHtmlCell<Gender> genderCell = new AbstractSafeHtmlCell<Gender>(
				new AbstractSafeHtmlRenderer<Gender>() {

					@Override
					public SafeHtml render(Gender object) {
						return template.img(object == Gender.MALE ? common.male().getSafeUri()
								: (object == Gender.FEMALE ? common.female().getSafeUri() : null));
					}
				}) {

			@Override
			protected void render(com.google.gwt.cell.client.Cell.Context context, SafeHtml data, SafeHtmlBuilder sb) {
				if (data != null) {
					sb.append(data);
				}

			}
		};
		this.lstUsers.addColumn(new Column<User, Gender>(genderCell) {

			@Override
			public Gender getValue(User object) {
				return object != null ? object.getGender() : null;
			}
		}, "Género");

		this.lstUsers.addColumn(new Column<User, SafeHtml>(new SafeHtmlCell()) {

			@Override
			public SafeHtml getValue(User user) {
				if (user != null) {
					if (user.getCouple() != null && !user.getCouple().getUserEmail().isEmpty()) {
						if (!user.getCouple().isFakeUser()) {
							return template.span("", user.getCouple().getNickName());
						} else if (user.getCoupleType() == CoupleType.SINGLE_USER) {
							return template.span("", template.i("Soltero"));
						}
					}

					if (user.getRequestsToYou() != null && !user.getRequestsToYou().isEmpty()) {
						return template.div(style.pendingRequests(), "Pendiente de confirmar pareja");
					}
				}

				return SafeHtmlUtils.EMPTY_SAFE_HTML;
			}
		}, "Emparejado con");

		this.lstUsers.setEmptyTableWidget(new HTML("<i>Ningún resultado</i>"));

		this.selectionModel = new SingleSelectionModel<User>(keyProvider);

		this.selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {

			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				presenter.onSelectedUserChanged();
			}
		});

		this.lstUsers.setSelectionModel(this.selectionModel);

		this.asyncDataProvider = new AsyncPagedDataProvider<User, Operation>(keyProvider, this, Operation.GettingUsers,
				this.operationManager, "");
		this.asyncDataProvider.addDataDisplay(lstUsers);
		pager = new SimplePager(TextLocation.CENTER, false, 0, true);
		pager.setDisplay(lstUsers);

		initWidget(uiBinder.createAndBindUi(this));
	}

	@UiHandler("searchBox")
	void onSearchBoxKeyPressed(KeyPressEvent evt) {
		if (this.enterPressed(evt) && this.searchBox.getValue() != null) {
			this.startSearch();
		}
	}

	@Override
	public void startSearch() {
		this.lstUsers.setVisibleRangeAndClearData(this.lstUsers.getVisibleRange(), true);
	}

	@Override
	public void setPagedDataProvider(PagedDataProvider<User> dataProvider) {
		this.pagedDataProvider = dataProvider;
		this.lstUsers.setPageSize(pagedDataProvider.getMinFecthLength());
	}

	@Override
	public PagedDataProvider<User> getPagedDataProvider() {
		return this.pagedDataProvider;
	}

	@Override
	public HasValue<String> searchBox() {
		return HasValueWrapper.from(searchBox, true, this);

	}

	@UiHandler("btnMakeCoupleRequest")
	void onMakeCoupleRequestButtonClicked(ClickEvent evt) {
		this.presenter.onMakeCoupleRequest();
	}

	@Override
	public User getSelectedUser() {
		return this.selectionModel.getSelectedObject();
	}

	@Override
	public void clearSelection() {
		this.selectionModel.clear();
	}

	@Override
	public HasVisibility ableToGetCoupleInfo() {
		return ableToGetCoupleInfo;
	}

	@Override
	public HasVisibility requestSentInfo() {
		return requestSentInfo;
	}

	@Override
	public HasVisibility unableToGetCoupleInfo() {
		return unableToGetCoupleInfo;
	}

	@Override
	public HasVisibility makeCoupleRequestActionVisibility() {
		return HasVisibilityWrapper.from(btnMakeCoupleRequest, this);
	}

	@Override
	public HasVisibility requestAlreadyMadeInfo() {
		return requestAlreadyMadeInfo;
	}

	@Override
	public void setLoading(boolean loading) {
		this.loading = loading;
		HasEnabledWrapper.setEnabled(!loading, btnMakeCoupleRequest, searchBox);
	}

	@Override
	public boolean isLoading() {
		return this.loading;
	}

	@Override
	public Info coupleGotInfo() {
		return this.coupleGotInfo;
	}

	@UiHandler("btnDismissRequest")
	void onDismissRequestButton(ClickEvent evt) {
		this.presenter.onDismissSelectedRequest();
	}
}
